package com.pi.pro.xcmg.am.was.fac.service;





import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.pi.common.CodesConstants;
import com.pi.common.utils.TextUtils;
import com.pi.core.exchange.vo.CommonNameRegistryService;
import com.pi.framework.core.util.StringUtils;
import com.pi.pro.xcmg.am.common.XcmgAmConstants;
import com.pi.pro.xcmg.am.common.XcmgAmSupport;
import com.pi.pro.xcmg.am.common.vo.act.MoveChangeDto;
import com.pi.pro.xcmg.am.common.vo.act.PickLabelDto;
import com.pi.pro.xcmg.am.was.edi.led.common.LedWasXcmgExchangeConstants;
import com.pi.pro.xcmg.am.was.edi.wcs.common.WcsWasExchangeSupport;
import com.pi.pro.xcmg.am.was.edi.wcs.common.WcsWasXcmgExchangeConstants;
import com.pi.pro.xcmg.am.was.edi.wcs.dto.*;
import com.pi.pro.xcmg.am.was.fac.handler.*;
import com.pi.sys.service.AlertService;
import com.pi.wms.common.WmsConstants;
import com.pi.wms.dto.act.TaskActionDto;
import com.pi.wms.dto.base.LocationLineDto;
import com.pi.wms.entity.*;
import com.pi.wms.fac.LocationResolver;
import com.pi.wms.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 *
 */
@Slf4j
@Service
public class WcsCustomWorkApiService {


    @Autowired
    private CommonNameRegistryService xwmsNameRegistryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private LineAcceptPalletizeDelegateHandler lineAcceptPalletizeDelegateHandler;

    @Autowired
    private LineAcceptMoveDelegateHandler lineAcceptMoveDelegateHandler;

    @Autowired
    private SrmDropDelegateHandler srmDropDelegateHandler;

    @Autowired
    private EpalMoveinRequestDelegateHandler epalMoveinRequestDelegateHandler;

    @Autowired
    private EpalReplenishDelegateHandler epalReplenishDelegateHandler;

    @Autowired
    private AlertService alertService;

    @Autowired
    private WasCustomWorkService wasCustomWorkService;

    @Autowired
    private WcsCustomWorkService wcsCustomWorkService;

    @Autowired
    private LedCustomWorkService ledCustomWorkService;

    @Autowired
    private LocationResolver locationResolver;

    private Cache<String, String> taskLocationCache= CacheBuilder.newBuilder().expireAfterWrite(20, TimeUnit.SECONDS).build();
    private Cache<String, String> taskReportCheckCache= CacheBuilder.newBuilder().expireAfterWrite(80, TimeUnit.SECONDS).build();
    private Cache<String, String> alarmCache= CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build();

    private Cache<String, String> moveRequestCache= CacheBuilder.newBuilder().expireAfterWrite(20, TimeUnit.SECONDS).build();
    //临时
    private Cache<String, String> containerOutsideCache= CacheBuilder.newBuilder().expireAfterWrite(4, TimeUnit.HOURS).build();



    //-----------------------------------------------------------------------
    // API
    //-----------------------------------------------------------------------

    /**
     * 入库请求
     */
    public String moveRequest(List<MoveRequestData> requestDatas, TaskActionDto actionDto){
        String m="";
        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);

        if ((requestDatas==null)|| (requestDatas.size()==0)){
            m="无有效的请求数据.";
            return m;
        }
        MoveRequestData md=requestDatas.get(0);

        String key=StringUtils.ifNullOrBlank(actionDto.getDivisionCode(), XcmgAmConstants.DIVISION_WH101_CODE)
                + "/" + md.getPalletCode()+"@" +md.getSiteCode();

        String tasktype=this.moveRequestCache.getIfPresent(key);
        if (!StringUtils.isNullOrBlank(tasktype)){
            m="正在处理.托盘码:"+md.getPalletCode();
            return m;
        }
        this.moveRequestCache.put(key, StringUtils.ifNullOrBlank(md.getType(), WcsWasXcmgExchangeConstants.TASK_TYPE_INBOUND));
        //
        MoveChangeDto changeDto=null;
        for (MoveRequestData t:requestDatas){
            if (t==null){
                continue;
            }
            changeDto = WcsWasExchangeSupport.translateTo(t);
            if (StringUtils.isNullOrBlank(changeDto.getRequestNumber())){
                changeDto.setRequestNumber(TextUtils.genBatchNumber());
            }
            changeDto.setLocationCode(this.wcsCustomWorkService.takeLocationcode(actionDto.getDivisionId(), t.getSiteCode()));
            m = this.moveRequest(changeDto, actionDto);
            if (!StringUtils.isNullOrBlank(m)){
                this.moveRequestCache.invalidate(key);
            }
        }
        //this.alertChecking(arrivalData, routeData);

        return m;
    }

    /**
     * 入库检测
     */
    public String checkStatus(InboundCheckData checkData, TaskActionDto actionDto){
        String m="";

        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);
        m = WcsWasExchangeSupport.check(checkData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        checkData.setSiteCode(this.wcsCustomWorkService.takeLocationcode(actionDto.getDivisionId(), checkData.getSiteCode()));
        TblLedMessage led=null;
        try{
            led=this.ledCustomWorkService.take(actionDto.getDivisionId(), checkData.getSiteCode());
            if (led==null){
                m="cant found led setting.site ode:"+checkData.getSiteCode();
                return m;
            }
            if (LedWasXcmgExchangeConstants.LED_WORK_TYPE_PUTAWAY_STATION.equalsIgnoreCase(led.getType())){
                if (WcsWasXcmgExchangeConstants.CHECK_TYPE_MOVE_REQ.equalsIgnoreCase(checkData.getBizType())){
                    m=this.ledCustomWorkService.showPutawayStationDefText(actionDto.getDivisionId(),checkData.getSiteCode());
                }
                if (WcsWasXcmgExchangeConstants.CHECK_TYPE_TU_STANCE.equalsIgnoreCase(checkData.getBizType())){
                    m=this.ledCustomWorkService.showPutawayStationExecuteError(actionDto.getDivisionId(),checkData.getSiteCode(), "", checkData.getMessage());
                }
            }
            if (LedWasXcmgExchangeConstants.LED_WORK_TYPE_PICK_STATION.equalsIgnoreCase(led.getType())){

                if (WcsWasXcmgExchangeConstants.CHECK_TYPE_MOVE_REQ.equalsIgnoreCase(checkData.getBizType())){
                    m=this.ledCustomWorkService.showPickStationDefText(actionDto.getDivisionId(),checkData.getSiteCode());
                }
                if (WcsWasXcmgExchangeConstants.CHECK_TYPE_TU_STANCE.equalsIgnoreCase(checkData.getBizType())){
                    m=this.ledCustomWorkService.showPickStationPickError(actionDto.getDivisionId(),checkData.getSiteCode(), "", checkData.getMessage());
                }
            }
        }catch (Exception e){
            e.getMessage();
            e.printStackTrace();
        }
        return m;
    }

    /**
     * 任务状态变更
     */
    public String taskChange(TaskReportData reportData, TaskActionDto actionDto){
        String m="";

        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);
        m = WcsWasExchangeSupport.check(reportData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        String fcode=this.taskFeaturecode(reportData);
        String token=this.taskLocationCache.getIfPresent(fcode);
        if (!StringUtils.isNullOrBlank(token)){
            m="task status is updating.task"+reportData.getCode();
            return m;
        }
        //
        reportData.setToSite(this.wcsCustomWorkService.takeLocationcode(actionDto.getDivisionId(), reportData.getToSite()));
        String tasktype="";
        String containnumber="";
        //
        LocationLineDto curloc=null;
        List<TwtActTaskList> tasks=null;
        TwtActTaskList task=null;
        String taskmode="";
        PickLabelDto pickLabelDto=null;
        if (WcsWasXcmgExchangeConstants.TASK_CHANGE_STATUS_FIN.equalsIgnoreCase(reportData.getStatus())){
            tasks = this.taskService.findByNumber(reportData.getCode().trim());
            if ((tasks==null)||(tasks.size()==0)){
                m="找不到任务,请确认任务是否已经结束.任务号:"+reportData.getCode();
                return m;
            }
            task=tasks.get(0);
            tasktype=task.getType();
            taskmode=task.getTaskMode();
            containnumber=task.getFromContainNumber();
            this.taskLocationCache.put(fcode, tasktype);
            token=this.taskReportCheckCache.getIfPresent(fcode);
            if (!StringUtils.isNullOrBlank(token)){
                m=this.wasCustomWorkService.taskCompleted(tasks, reportData.getToSite());
                if (StringUtils.isNullOrBlank(m)){
                    return m;
                }
                if (m.startsWith(XcmgAmConstants.RESULT_CODE_EDI_WARN_GONO)){
                    m="";
                    return m;
                }
            }
            actionDto.setWorker("WCS_TASK_REPORTER/");
            m = this.wasCustomWorkService.taskFinish(tasks, reportData.getToSite(), CodesConstants.SYSTEM_WCS, actionDto);
            if ((StringUtils.isNullOrBlank(m))&& (XcmgAmConstants.TASK_MODE_RETURN_ACTION.equalsIgnoreCase(taskmode))){
                m=XcmgAmConstants.RESULT_CODE_EDI_WARN_RETRUN;
            }
            this.taskReportCheckCache.put(fcode, tasktype);

            if (WmsConstants.TASK_TYPE_PICK.equalsIgnoreCase(tasktype)){
                this.wcsCustomWorkService.showPickingTask(task.getDivisionId(), task.getFromContainNumber(), reportData.getToSite());
            }

            if (WmsConstants.TASK_TYPE_COUNT.equalsIgnoreCase(tasktype)){
                this.wcsCustomWorkService.showCountTask(task.getDivisionId(), task.getFromContainNumber(), reportData.getToSite());
            }

            //补充空托盘位,清除空托
            if (XcmgAmConstants.LOCATION_CODE_PA1054.equalsIgnoreCase(reportData.getToSite())){
                this.wasCustomWorkService.releaseEpal(containnumber);
            }

            //
            curloc=this.locationResolver.lookup(task.getDivisionId(), reportData.getToSite());
            if (curloc!=null){
                if (!WmsConstants.LOCATION_TYPE_BIN.equalsIgnoreCase(curloc.getLocationType())){
                    this.arrivalAtOutsideCache(containnumber, curloc.getLocationCode());
                }else {
                    this.cleanOutsideCache(containnumber);
                }
            }
            //
            if ((WmsConstants.TASK_TYPE_PICK.equalsIgnoreCase(tasktype))
                    && (CodesConstants.COMMON_FLAG_YES.equalsIgnoreCase(XcmgAmConstants.openPickLabelPrint))){
                pickLabelDto=this.wasCustomWorkService.createPickLabel(task);
                this.wasCustomWorkService.printPickLabel(task, pickLabelDto);
            }
        }
        if (WcsWasXcmgExchangeConstants.TASK_CHANGE_STATUS_WORK.equalsIgnoreCase(reportData.getStatus())){

        }
        if (WcsWasXcmgExchangeConstants.TASK_CHANGE_STATUS_CANCEL.equalsIgnoreCase(reportData.getStatus())){

        }
        return m;
    }

    /**
     * 站台状态变更/堆垛机
     */
    public String deviceChange(StationReportData reportData, TaskActionDto actionDto){
        String m="";

        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);
        m = WcsWasExchangeSupport.check(reportData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (WcsWasXcmgExchangeConstants.STATION_CHANGE_STATUS_FREE.equalsIgnoreCase(reportData.getStatus())){

        }
        if (WcsWasXcmgExchangeConstants.STATION_CHANGE_STATUS_OCCUPY.equalsIgnoreCase(reportData.getStatus())){

        }
        if (WcsWasXcmgExchangeConstants.STATION_CHANGE_STATUS_DISABLED.equalsIgnoreCase(reportData.getStatus())){

        }
        return m;
    }

    /**
     * 呼叫空托
     */
    public String epalReplenish(EPalletRequestData requestData, TaskActionDto actionDto){
        String m="";

        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);
        m = WcsWasExchangeSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        //
        if ((requestData.getQuantity()==null) || (requestData.getQuantity().compareTo(0)<=0)){
            requestData.setQuantity(1);
        }

        String fcode=this.taskFeaturecode(actionDto.getDivisionCode(), requestData);
        String token=this.taskLocationCache.getIfPresent(fcode);
        if (!StringUtils.isNullOrBlank(token)){
            m="call pallet is working.location"+requestData.getCode();
            return m;
        }
        //
        requestData.setCode(this.wcsCustomWorkService.takeLocationcode(actionDto.getDivisionId(), requestData.getCode()));
        if (XcmgAmConstants.DIVISION_WH101_CODE.equalsIgnoreCase(actionDto.getDivisionCode())) {
            if (!XcmgAmConstants.wh101EpalReplStations.containsKey(requestData.getCode())){
                m="非有效空托请求站点.";
                return m;
            }
        }

        if (!StringUtils.isNullOrBlank(requestData.getType())){
            if (WcsWasXcmgExchangeConstants.CONTAINER_TYPE_TOTE.equalsIgnoreCase(requestData.getType())){
                requestData.setType(XcmgAmConstants.CONTAINER_TYPE_TOTE);
            }else if (WcsWasXcmgExchangeConstants.CONTAINER_TYPE_PALLET.equalsIgnoreCase(requestData.getType())){
                requestData.setType(XcmgAmConstants.CONTAINER_TYPE_PALLET);
            }
        }
        if (StringUtils.isNullOrBlank(requestData.getType())){
            requestData.setType(XcmgAmConstants.CONTAINER_TYPE_TOTE);
        }
        actionDto = this.wasCustomWorkService.defDivisionWork(actionDto);
        m = WcsWasExchangeSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        //
        if ((requestData.getQuantity()==null) || (requestData.getQuantity().compareTo(0)<=0)){
            requestData.setQuantity(1);
        }

        if (XcmgAmConstants.DIVISION_WH101_CODE.equalsIgnoreCase(actionDto.getDivisionCode())) {
            if (!XcmgAmConstants.wh101EpalReplStations.containsKey(requestData.getCode())){
                m="非有效空托请求站点.";
                return m;
            }
        }
        m=this.wasCustomWorkService.replenishEpal(actionDto.getDivisionId(), requestData.getCode(), requestData.getType(), requestData.getQuantity());
        return m;
    }





    //-----------------------------------------------------------------------
    // FUNC/II
    //-----------------------------------------------------------------------
    // MOVE-REQ
    private String moveRequest(MoveChangeDto requestData, TaskActionDto actionDto){
        String m="";
        m=XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }

        //PAL-RECV-REQ
        Map<String, String>  locs= XcmgAmSupport.palletizeRequestStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtPalletizeRequestStation(requestData, actionDto);
            return m;
        }

        //SHIP-CLOSE
        locs= XcmgAmSupport.shipCloseStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtShipcloseStation(requestData, actionDto);
            return m;
        }

        //MOVEIN-REQ
        locs= XcmgAmSupport.moveinRequestStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtMoveinRequestStation(requestData, actionDto);
            return m;
        }

        //EPAL-MOVEIN-REQ
        locs= XcmgAmSupport.epalMoveinRequestStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtEpalMoveinRequestStation(requestData, actionDto);
            return m;
        }

        //SRM-DROP
        locs= XcmgAmSupport.srmDropStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtSrmDropStation(requestData, actionDto);
            return m;
        }

        //EPAL-REPL
        locs= XcmgAmSupport.epalReplenishStation(requestData.getDivisionCode());
        if (locs.containsKey(requestData.getLocationCode())){
            m = this.movereqAtEpalReplenishStation(requestData, actionDto);
            return m;
        }
        return m;
    }

    //-----------------------------------------------------------------------
    // FUNC/III
    //-----------------------------------------------------------------------
    ////
    private String movereqAtPalletizeRequestStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.lineAcceptPalletizeDelegateHandler!=null){
            m = this.lineAcceptPalletizeDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }

    private String movereqAtShipcloseStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.lineAcceptMoveDelegateHandler!=null){
            m = this.lineAcceptMoveDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }

    private String movereqAtMoveinRequestStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.lineAcceptMoveDelegateHandler!=null){
            m = this.lineAcceptMoveDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }

    private String movereqAtEpalMoveinRequestStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.epalMoveinRequestDelegateHandler!=null){
            m = this.epalMoveinRequestDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }

    private String movereqAtSrmDropStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.srmDropDelegateHandler!=null){
            m = this.srmDropDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }

    private String movereqAtEpalReplenishStation(MoveChangeDto requestData, TaskActionDto actionDto){
        String m = "";
        m = XcmgAmSupport.check(requestData);
        if (!StringUtils.isNullOrBlank(m)){
            return m;
        }
        if (this.epalReplenishDelegateHandler!=null){
            m = this.epalReplenishDelegateHandler.perform(requestData, actionDto);
        }
        return m;
    }






    //---------------------------------------------------------
    // 到位
    //---------------------------------------------------------


    //---------------------------------------------------------
    // 到位
    //---------------------------------------------------------

    public void arrivalAtOutsideCache(String containerNumber, String locationCode){
        if (StringUtils.isNullOrBlank(containerNumber)){
            return;
        }
        if (StringUtils.isNullOrBlank(locationCode)){
            locationCode=CodesConstants.COMMON_WILDCARD;
        }
        containerNumber=containerNumber.trim();
        this.containerOutsideCache.put(containerNumber, locationCode);
    }

    public void cleanOutsideCache(String containerNumber){
        if (StringUtils.isNullOrBlank(containerNumber)){
            return;
        }
        containerNumber=containerNumber.trim();
        this.containerOutsideCache.invalidate(containerNumber);
    }

    public boolean containerAtOutside(String containerNumber){
        boolean state=false;
        if (StringUtils.isNullOrBlank(containerNumber)){
            return state;
        }
        containerNumber=containerNumber.trim();
        String loccode=this.containerOutsideCache.getIfPresent(containerNumber);
        if (StringUtils.isNullOrBlank(loccode)){
            return state;
        }
        state=true;
        return state;
    }

    //---------------------------------------------------------
    //
    //---------------------------------------------------------
    //
    private String alertChecking(MoveChangeDto changeDto, String containerNumber, String locationCode){
        String m = ""; //AvicWuhanExchangeSupport.messageText(routeData, containerNumber, locationCode);
        if (StringUtils.isNullOrBlank(m)){
            return m;
        }

        if (StringUtils.isNullOrBlank(containerNumber)){
            containerNumber=CodesConstants.COMMON_WILDCARD;
        }
        if (StringUtils.isNullOrBlank(locationCode)){
            locationCode=CodesConstants.COMMON_WILDCARD;
        }
        String key=containerNumber+":"+locationCode;
        String flag=this.alarmCache.getIfPresent(key);
        if  ((flag==null) || (!CodesConstants.COMMON_FLAG_YES.equalsIgnoreCase(flag))){
            alertService.publishAlarm(CodesConstants.SYSTEM_WMS, "MOVE", locationCode, containerNumber, m, 1L, false, "TU.ARRIVAL", null, "", CodesConstants.COMMON_HOLD_STATUS_CLOSED,"");
            this.alarmCache.put(key,CodesConstants.COMMON_FLAG_YES);
        }
        return m;
    }

    private String taskFeaturecode(TaskReportData reportData){
        if (reportData==null){
            return CodesConstants.COMMON_WILDCARD;
        }
        return reportData.getCode()+":"+StringUtils.ifNullOrBlank(reportData.getToSite(), CodesConstants.COMMON_WILDCARD);
    }

    private String taskFeaturecode(String divisionCode, EPalletRequestData requestData){
        if (StringUtils.isNullOrBlank(divisionCode)){
            divisionCode=XcmgAmConstants.DIVISION_WH101_CODE;
        }
        if (requestData==null){
            return CodesConstants.COMMON_WILDCARD;
        }
        return divisionCode+"/"+"EPAL_REPL"+":"+ StringUtils.ifNullOrBlank(requestData.getCode(), CodesConstants.COMMON_WILDCARD)+"/"+StringUtils.ifNullOrBlank(requestData.getType(), XcmgAmConstants.CONTAINER_TYPE_TOTE);
    }




}
